# -*- coding: utf-8 -*-

from .ir_type import IType
from .ir_var import IVar
from .ir_statement import IOpBody, IExp, str_indent


class ITask:
    def __init__(self, name: str, body: IOpBody):
        self.name = name
        self.body = body

    def __str__(self):
        return 'Task {}:\n{}'.format(self.name, str_indent(str(self.body)))


def dump_dict(data: dict):
    return '\n'.join(('  ' + key + ': ' + str(data[key])) for key in data)


# Paramsters
class IVarParam(IVar):
    def __init__(self, name: str, type: IType):
        super(IVarParam, self).__init__(name, type)

    def __str__(self):
        return 'param.{}'.format(self.name)


# Registers
class IVarReg(IVar):
    def __init__(self, name: str, type: IType):
        super(IVarReg, self).__init__(name, type)

    def __str__(self):
        return 'reg.{}'.format(self.name)


# Constants
class IVarConst(IVar):
    def __init__(self, name: str, type: IType, exp: IExp):
        super(IVarConst, self).__init__(name, type)
        self.exp = exp

    def __str__(self):
        return 'const.{}'.format(self.name)


# Temperary variables
class IVarTemp(IVar):
    def __init__(self, name: str, type: IType):
        super(IVarTemp, self).__init__(name, type)

    def __str__(self):
        return self.name


# Ports
class IVarPort(IVar):
    def __init__(self, name: str, type: IType, exp: IExp):
        super(IVarPort, self).__init__(name, type)
        self.exp = exp

    def __str__(self):
        return 'port.{}'.format(self.name)


class ITypeNode(IType):
    def __init__(self, name: str):
        super(ITypeNode, self).__init__('Node', -1)
        self.name = name
        # Save the type helper.
        self.helper = None
        # Define variable types list.
        self.params = {}
        self.ports = {}
        self.consts = {}
        self.regs = {}
        self.nodes = {}
        # Define the task lists.
        self.initial = None
        self.tasks = None
        self.task_body = []
        self.ir_methods = []

    def dump(self):
        if self.initial is None:
            s_init = ''
        else:
            s_init = 'Init:\n{}\n'.format(str_indent(str(self.initial)))
        return 'Node {}\ntasks = {}\n{}{}'.format(
            self.name, self.tasks, s_init,
            '\n'.join(str(x) for x in self.task_body))

    def __str__(self):
        return 'Node<{}>'.format(self.name)


class IVarNode(IVar):
    def __init__(self, name: str, node_type: ITypeNode):
        super(IVarNode, self).__init__(name, node_type)

    def __str__(self):
        return 'node.{}'.format(self.name)


class IExpThis(IExp):
    def __init__(self, node_type: ITypeNode):
        super(IExpThis, self).__init__(IType('this', -1))
        self.node_type = node_type

    def __str__(self):
        return 'this'
